package hn.sigit.view.workflow.permits;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.model.SelectItem;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.bpm.EndTask;
import hn.sigit.dao.hnd.administrative.HND_PermitDAO;
import hn.sigit.dao.ladm.external.ExtPartyDAO;
import hn.sigit.logic.bpm.ArchiveRepository;
import hn.sigit.logic.bpm.AttachedFileData;
import hn.sigit.logic.general.GeneralHelperX;
import hn.sigit.logic.general.ResourceBundleHelper;
import hn.sigit.logic.general.SpatialAnalysisHelper.SpatialAnalysisResult;
import hn.sigit.model.hnd.administrative.HND_Permit;
import hn.sigit.model.hnd.administrative.HND_PermitObservation;
import hn.sigit.model.hnd.administrative.HND_PermitRuleGroup;
import hn.sigit.model.hnd.administrative.HND_SpatialRule;
import hn.sigit.model.ladm.administrative.LA_AdministrativeSource;
import hn.sigit.model.ladm.external.ExtParty;
import hn.sigit.view.workflow.WorkflowHelper;


public abstract class PermitHelper extends WorkflowHelper {
	protected HND_Permit permit;
	protected Long permitId;
	private Long partyId;
	private String partyNationalIdentity;
	private String partyName;
	private String cashiersCode;
	private BigDecimal payment;

	
	private boolean approveTransaction;

	protected HND_PermitRuleGroup ruleGroup;
	protected List<HND_PermitRuleGroup> permitRuleGroupList;
	protected List<SelectItem> permitRuleGroupItemList;
	protected List<HND_PermitObservation> permitObservations;

	@In
	protected ResourceBundleHelper resBundle;
	
	@In
	protected GeneralHelperX generalHelper;

	private PermitRuleGroupConverter permitRuleGroupConverter;

	
	public Long getPermitId() {
		return permitId;
	}
	public void setPermitId(Long permitId) {
		this.permitId = permitId;
	}
	
	public Long getPartyId() {
		return partyId;
	}
	public void setPartyId(Long partyId) {
		this.partyId = partyId;
	}
	
	public String getPartyNationalIdentity() {
		return this.partyNationalIdentity;
	}
	public void setPartyNationalIdentity(String partyNationalIdentity) {
		this.partyNationalIdentity = partyNationalIdentity;
	}
	
	public String getPartyName() {
		return partyName;
	}
	public void setPartyName(String partyName) {
		this.partyName = partyName;
	}
	
	public String getCashiersCode() {
		return cashiersCode;
	}
	public void setCashiersCode(String cashiersCode) {
		this.cashiersCode = cashiersCode;
	}
	
	public BigDecimal getPayment() {
		return payment;
	}
	public void setPayment(BigDecimal payment) {
		this.payment = payment;
	}
	
	

	
	public void acceptSelectedFile() {
		if (permit != null && permit.getId() == null) {
			if ("0".equals(editMode)) { //agregando
				if (null == attachedFiles)
					attachedFiles = new ArrayList<AttachedFileData>();
				attachedFiles.add(selectedFile);
			}
			else if ("1".equals(editMode)) { //editando
				attachedFiles.set(currentRow, selectedFile);
			}
		}
		else if (permit != null) {
			permit.getSources().add(ArchiveRepository.addToRepository(appOptions, selectedFile));
			HND_PermitDAO.save(permit);
		}
		
		setSelectedFile(null);
		fileSources = null;
	}

	
	public String hasAttachedFiles() {
		if (attachInfo)
			return "attaches";
		
		return "does_not_attach";
	}
	
	public List<LA_AdministrativeSource> getFileSources() {
		if (fileSources == null) {
			//TODO: we could add an ordering criterion
			fileSources = new ArrayList<LA_AdministrativeSource>();
			if (permit != null && permit.getSources() != null)
				for (LA_AdministrativeSource source : permit.getSources())
					fileSources.add(source);
		}
		
		return fileSources;
	}
	
	public List<HND_PermitObservation> getPermitObservations() {
		if (permitObservations == null) {
			permitObservations = new ArrayList<HND_PermitObservation>();
			if (permit != null && permit.getPermitObservations() != null)
				for (HND_PermitObservation po : permit.getPermitObservations())
					permitObservations.add(po);
		}
		return permitObservations;
	}
	
	public String selectZoneFromMap() {
		if (permit != null) {
			permit.setSpatialZone( interactiveViewerHelper.getSelectedZone() );
		}
		return null;
	}
	
	public boolean isApproveTransaction() {
		return approveTransaction;
	}
	public void setApproveTransaction(boolean approveTransaction) {
		this.approveTransaction = approveTransaction;
	}
	
	public HND_PermitRuleGroup getRuleGroup() {
		return ruleGroup;
	}
	public void setRuleGroup(HND_PermitRuleGroup ruleGroup) {
		this.ruleGroup = ruleGroup;
	}
	
	@EndTask
	public String endTask() {
		return "home";
	}
	
	@EndTask
	public String endPresentationTask() {
		permit.setReceptionistUserName(actor.getId());
		permit.setReceptionistFullName(loggedUserFullName);
		
		return "home";
	}
	
	@EndTask
	public String endAnalysisTask() {
		if (!spatialAnalysisHelper.getSpatialRuleToAnalysisMap().isEmpty()) {
			//new spatial analysis was made, so need to clear current observations
			permit.getPermitObservations().clear();
			for (HND_PermitObservation po : getSarToPermitObsMap().values())
				permit.getPermitObservations().add(po);
		}
		
		permit.setAnalystUserName(actor.getId());
		permit.setAnalystFullName(loggedUserFullName);
		if (ruleGroup != null) {
			permit.setRuleGroup(ruleGroup);
			permit.setRuleGroupName(ruleGroup.getName() + " - " + ruleGroup.getDescription());
		}
		
		HND_PermitDAO.save(permit);

		return "home";
	}
	
	@EndTask
	public String endApprovalTask() {
		permit.setApproved(approveTransaction);
		permit.setApproverUserName(actor.getId());
		permit.setApproverFullName(loggedUserFullName);
		permit.setIssueDate(new Date());
		
		HND_PermitDAO.save(permit);
		
		return "home";
	}
	
	@EndTask(transition="approval_back2analysis")
	public String approvalBackToAnalysis() {
		permit.setApproverUserName(actor.getId());
		permit.setApproverFullName(loggedUserFullName);

		HND_PermitDAO.save(permit);
		
		return "home";
	}

	protected void beginProcessAux(HND_Permit hndPermit) {
		hndPermit.setRequestDate(new Date());
		hndPermit.setReceptionistUserName(actor.getId());
		hndPermit.setReceptionistFullName(loggedUserFullName);

		ExtParty extParty = ExtPartyDAO.loadExtPartyByExtPID(getPartyId());
		hndPermit.setExtParty(extParty);
		
		List<AttachedFileData> attachedFiles = getAttachedFiles();
		if (attachedFiles != null) {
			Set<LA_AdministrativeSource> adminSources = hndPermit.getSources();
			if (adminSources == null) {
				adminSources = new HashSet<LA_AdministrativeSource>();
				hndPermit.setSources(adminSources);
			}
			
			LA_AdministrativeSource adminSource;
			for (AttachedFileData afd : attachedFiles) {
				adminSource = ArchiveRepository.addToRepository(appOptions, afd);
				adminSources.add(adminSource);
			}
		}
	}

	public List<SelectItem> getPermitRuleGroupItemList() {
		if (permitRuleGroupItemList == null) {
			permitRuleGroupItemList = new ArrayList<SelectItem>();
			permitRuleGroupItemList.add(new SelectItem(null, "(seleccionar)"));
			for (HND_PermitRuleGroup prg : getPermitRuleGroupList())
				permitRuleGroupItemList.add(new SelectItem(prg, prg.getName() + " - " + prg.getDescription()));
		}
		return permitRuleGroupItemList;
	}
	
	public List<HND_SpatialRule> getRuleList() {
		return spatialAnalysisHelper.getRuleGroupRules();
	}
	
	private Map<SpatialAnalysisResult, HND_PermitObservation> getSarToPermitObsMap() {
		Map<SpatialAnalysisResult, HND_PermitObservation> sarToPermitObsMap = new HashMap<SpatialAnalysisResult, HND_PermitObservation>();
		HND_PermitObservation permitObservation;
		for (HND_SpatialRule spatialRule : getRuleList()) {
			List<SpatialAnalysisResult> sarList = spatialAnalysisHelper.getSpatialRuleToAnalysisMap().get(spatialRule);
			for (SpatialAnalysisResult sar : sarList) {
				permitObservation = new HND_PermitObservation();
				permitObservation.setPermit(permit);
				permitObservation.setSpatialRuleName(spatialRule.getCode());
				permitObservation.setSpatialRuleDescription(spatialRule.getDescription());
				permitObservation.setSpatialRuleDetails(generalHelper.spatialRuleDetailsText(spatialRule));
				permitObservation.setAction(spatialRule.getAction());
				permitObservation.setTargetSpatialZone(sar.getRhsSpatialZone());
				permitObservation.setAnalystObservation(sar.getAnalystObservation());

				sarToPermitObsMap.put(sar, permitObservation);
			}
		}
		
		return sarToPermitObsMap;
	}

	
	public Converter getPermitRuleGroupConverter() {
		if (permitRuleGroupConverter == null) {
			permitRuleGroupConverter = new PermitRuleGroupConverter();
		}
		return permitRuleGroupConverter;
	}
	
	
	
	public abstract List<SelectItem> getPermitTypeValueList();
	public abstract List<HND_PermitRuleGroup> getPermitRuleGroupList();

	
	public class PermitRuleGroupConverter implements Converter {
		@Override
		public Object getAsObject(FacesContext context, UIComponent component,
				String value) {
			for (HND_PermitRuleGroup prg : getPermitRuleGroupList())
				if (String.valueOf(prg.getId()).equals(value))
					return prg;
			return null;
		}

		@Override
		public String getAsString(FacesContext context, UIComponent component,
				Object value) {
			if (value == null) return "";
			return String.valueOf(((HND_PermitRuleGroup) value).getId());
		}
	}
}

